import React, { useEffect, useRef, useState } from 'react';
import { Factory } from 'vexflow';

export const App = () => {
    const sheetMusicRef = useRef(null);
    const markersContainerRef = useRef(null);
    const [score, setScore] = useState(0);
    const [isPlaying, setIsPlaying] = useState(false);
    const [startTime, setStartTime] = useState(null);
    const [taps, setTaps] = useState([]);
    const [currentBeat, setCurrentBeat] = useState(0);
    const [notePositions, setNotePositions] = useState([]);
    const vfRef = useRef(null);

    const expectedBeats = [0, 1000, 2000, 3000];
    const TOLERANCE_MS = 150;

    useEffect(() => {
        // 这个只是用来设置 五线谱的
        if (!sheetMusicRef.current) return;
        sheetMusicRef.current.innerHTML = '';

        try {
            const vf = new Factory({
                renderer: {
                    elementId: 'sheet-music',
                    width: 400,
                    height: 200
                }
            });

            const score = vf.EasyScore();
            const system = vf.System();

            const voice = score.voice(score.notes('B4/q, B4/q, B4/q, B4/q', { stem: 'up' }));

            const stave = system.addStave({
                voices: [voice]
            }).addClef('treble').addTimeSignature('4/4');

            vf.Formatter()
                .joinVoices([voice])
                .formatToStave([voice], stave);

            const positions = [];
            voice.getTickables().forEach((note) => {
                positions.push({
                    x: note.getAbsoluteX(),
                    width: note.getWidth()
                });
            });

            setNotePositions(positions);
            vf.draw();
            vfRef.current = vf;

            const container = document.createElement('div');
            container.className = 'markers-container';
            container.style.position = 'absolute';
            container.style.top = '160px';
            container.style.left = '0';
            container.style.right = '0';
            container.style.height = '20px';
            container.style.pointerEvents = 'none';
            sheetMusicRef.current.appendChild(container);
            markersContainerRef.current = container;
        } catch (error) {
            console.error('Error initializing VexFlow:', error);
        }
    }, []);

    const drawMarkers = () => {
        if (!markersContainerRef.current || notePositions.length === 0) return;

        const existingMarkers = markersContainerRef.current.querySelectorAll('.rhythm-marker');
        existingMarkers.forEach(marker => marker.remove());

        taps.forEach((tap) => {
            if (tap.position >= 0 && tap.position < notePositions.length) {
                const marker = document.createElement('div');
                marker.className = 'rhythm-marker';
                marker.style.position = 'absolute';
                marker.style.left = `${notePositions[tap.position].x}px`;
                marker.style.width = '12px';
                marker.style.height = '12px';
                marker.style.borderRadius = '50%';
                marker.style.backgroundColor = tap.isCorrect ? '#4CAF50' : '#F44336';
                marker.style.transform = 'translateX(-50%)';
                markersContainerRef.current?.appendChild(marker);
            }
        });

        if (isPlaying && currentBeat < notePositions.length) {
            const currentBeatMarker = document.createElement('div');
            currentBeatMarker.className = 'rhythm-marker current-beat';
            currentBeatMarker.style.position = 'absolute';
            currentBeatMarker.style.left = `${notePositions[currentBeat].x}px`;
            currentBeatMarker.style.width = '16px';
            currentBeatMarker.style.height = '16px';
            currentBeatMarker.style.borderRadius = '50%';
            currentBeatMarker.style.border = '2px solid #2196F3';
            currentBeatMarker.style.transform = 'translateX(-50%)';
            currentBeatMarker.style.transition = 'left 0.1s ease-out';
            markersContainerRef.current?.appendChild(currentBeatMarker);
        }
    };

    useEffect(() => {
        drawMarkers();
    }, [taps, currentBeat, isPlaying, notePositions]);

    useEffect(() => {
        // 只渲染一次，用来干啥的
        // 组件挂载（mount） 和 卸载（unmount） 防止内存泄露
        return () => {
            if (markersContainerRef.current) {
                markersContainerRef.current.remove();
            }
        };
    }, []);

    const startExercise = () => {
        setIsPlaying(true);
        setStartTime(Date.now());
        setTaps([]);
        setScore(0);
        setCurrentBeat(0);

        const beatInterval = setInterval(() => {
            setCurrentBeat((prev) => {
                if (prev >= 3) {
                    clearInterval(beatInterval);
                    setIsPlaying(false);
                    return prev;
                }
                return prev + 1;
            });
        }, 1000);
    };

    const handleTap = () => {
        if (!isPlaying || !startTime) return;

        const currentTime = Date.now();
        const tapTime = currentTime - startTime;

        const closestBeat = expectedBeats.reduce((prev, curr) => {
            return Math.abs(curr - tapTime) < Math.abs(prev - tapTime) ? curr : prev;
        });

        const beatIndex = expectedBeats.indexOf(closestBeat);
        const isCorrect = Math.abs(tapTime - closestBeat) <= TOLERANCE_MS;

        const newTap = {
            time: tapTime,
            position: beatIndex,
            isCorrect: isCorrect
        };

        setTaps(prev => [...prev, newTap]);

        if (isCorrect) {
            setScore(prev => prev + 1);
        }
    };

    return (
        <div className="py-8 text-base leading-6 space-y-4 text-gray-700 sm:text-lg sm:leading-7">
            <h1 className="text-2xl font-bold mb-8 text-center">Rhythm Trainer</h1>
            <div id="sheet-music" ref={sheetMusicRef}
                 className="border rounded p-4 mb-8 mx-auto relative"
                 style={{width: '800px'}}></div>
            <div className="flex justify-center gap-4 mb-8">
                <button
                    onClick={startExercise}
                    className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
                    disabled={isPlaying}
                >
                    {isPlaying ? 'Playing...' : 'Start'}
                </button>
            </div>
            <div
                onClick={handleTap}
                className={`w-64 h-40 flex items-center justify-center rounded-lg cursor-pointer transition-colors duration-150 ${
                    isPlaying ? 'bg-green-100 hover:bg-green-200' : 'bg-gray-100'
                }`}
                style={{border: '1px solid #ccc'}} // 增加边框便于观察位置
            >
                <div className="text-center">
                    <p>Tap to play the rhythm</p>
                </div>
            </div>


        </div>
    );
}
